#pragma once
#include "Socket.hpp"
#include <signal.h>

extern Log log;

/*
目前使用的是SvrCal.hpp中的
string doCalculate(const string& text)
*/
using fun_t = function<string(string&)>;

class TcpSvr
{
public:
    TcpSvr();
    TcpSvr(uint16_t port, fun_t callback) : _port(port), _callBack(callback) {}
    bool initSvr();
    void startSvr();
private:
    uint16_t _port;
    Sock _listSock;
    fun_t _callBack;
};

inline bool TcpSvr::initSvr()
{
    _listSock.Socket();
    _listSock.Bind(_port);
    _listSock.Listen();
    log(INFO, "TcpSvr Init over.\n");
}

inline void TcpSvr::startSvr()
{
    signal(SIGCHLD, SIG_IGN);
    for(;;) {
        string peerIp; 
        uint16_t peerPort;

        int socketFd = _listSock.Accept(&peerIp, &peerPort);
        if(socketFd < 0) {
            sleep(1);
            continue;
        }
        log(INFO, "TcpSvr is Accepting, client IP: %s, clientPort %d\n", peerIp.c_str(), peerPort);

        pid_t id = fork();
        if(id < 0) {
            log(WARNING, "TcpSvr::startSvr() fork error!\n");
            sleep(1);
            continue;
        } else if(id == 0) {
            // 关闭_listenFd的目的是为了防止子进程修改父进程文件描述符下的内容
            _listSock.Close();
            string inStr="";
            for(;;) {
                char buf[128];
                ssize_t n = read(socketFd, buf, sizeof buf);
                if (n < 0) {
                    log(WARNING, "TcpSvr::startSvr() read error!\n");
                    // sleep(1);
                    break;
                } else if(n == 0) {
                    log(WARNING, "TcpSvr::startSvr() read over!\n");
                    // sleep(1);
                    break;
                } else {
                    buf[n] = 0;
                    inStr += buf;
                    log(DEBUG, "Read from clinet: \n%s", inStr.c_str());
                    fflush(stdout);

                    while (true) {
                        // 客户端可能发送多次数据，所以这里一次全部处理干净
                        // 回调函数，计算结果
                        string r = _callBack(inStr);
                        if(r == "") {
                            // 报文不正确，重新读取。也有可能是已经将报文全部处理完，发送给客户端了
                            // log(WARNING, "TcpSvr::startSvr() doCalculate error!\n");
                            break;
                            // sleep(1);
                        }
                        write(socketFd, r.c_str(), r.size());
                    }
                }
            }   
            exit(0);
        } else {
            // 父进程关闭socketFd的意义是为了防止文件描述符越用越少，关闭了之后能保证每一个新的进程用的都是fd都是4
            close(socketFd);
        }
    }
}